/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "local_net_communication.h"
#include "local_net_utils.h"
#include "local_net_udp.h"
#include "local_net_def.h"

#include <string.h>
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <errno.h>

#include <sys/time.h>
#include <cJSON.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <math.h>

#ifdef L2_DEVICE
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#endif

#ifdef L0_DEVICE
   #define WLAN_NAME "wlan0"   // 无线设备使用："wlan0"
#elif defined(L2_DEVICE)
   #define WLAN_NAME "wlan0"    // l2设备插网线时候是eth0, 否则 wlan0
#endif

#define DISC_PORT       50000
#define BC_SLEEP_TIME   5
#define EXEC_SUCC 0
#define EXEC_FAILED -1
#define BROADCAST_ARRSIZE 1024

#define MSG_SZ 1024

// 解析的类型
const char* BROADCAST = "broadcast";
const char* UNICAST = "command";
const char* RESPONSE = "response";

typedef struct {
    uint8_t msgId;
    char deviceId[DEVICE_ID_LEN];
} LocalNetMsgRespData;

typedef struct {
    char subscribe[32];
    char group[32];
} DestDevIdCheckData;

typedef struct {
    void *next;
    char destDevId[DEVICE_ID_LEN];
} DeviceIdHang;

typedef struct {
    char *msg;
    uint8_t sendCnt;
    uint8_t msgId;
    struct timeval time;
    char publish[32];
    DeviceIdHang *pDestDevId;
} LocalNetMsgSendNode;

typedef struct {
    uint8_t msgIdCnt;
    Node_t *list;
#ifdef L0_DEVICE
    osMutexId_t listMutex;
#elif defined(L2_DEVICE)
    pthread_mutex_t listMutex;
#endif
} LocalNetMsgSendList;
typedef LocalNetMsgSendList* MsgSendListHandle;

typedef int8_t (*LocalNetRecvCb)(const char *msg);

typedef int8_t (*LocalNetDevListNoticeCb)(Node_t *devList);

typedef struct {
    LocalNetThreadStatus recvMsgDealThreadStatus;
    LocalNetThreadStatus devOfflineJudgeThreadStatus;
    LocalNetThreadStatus sendMsgDealThreadStatus;
    MsgSendListHandle sendReadyMsgList;    // 待发送信息列表
    Node_t *onlineDevList;    // 在线设备列表
    LocalNetRecvCb recvCb;    // 数据接收回调
    LocalNetDevListNoticeCb devListNoticeCb;    // 在线设备变化通知回调
#ifdef L0_DEVICE
    osThreadId_t recvMsgDealThread;    // 数据接收处理线程
    osMessageQueueId_t recvMsgDealQueue;    // 数据接收处理消息队列
    osThreadId_t devOfflineJudgeThread;    // 设备在线判断线程
    osThreadId_t sendMsgDealThread;    // 消息发送线程
#elif defined(L2_DEVICE)
    pthread_t recvMsgDealThread;    // 数据接收处理线程
    key_t key;                  // 消息队列msgid所对应的key
    MSG_QUEUE_ID recvMsgDealQueue;    // 数据接收处理消息队列
    pthread_t devOfflineJudgeThread;    // 设备在线判断线程
    pthread_t sendMsgDealThread;    // 消息发送线程
#endif
} LocalNetCommController;

static LocalNetCommController g_localNetCommCtl;

static MsgSendListHandle LocalNetMsgSendListInit(void)
{
    MsgSendListHandle msgSendList = (MsgSendListHandle)malloc(sizeof(LocalNetMsgSendList));
    if(!msgSendList) {
        LOG_E("malloc msg send list handle failed!");
        return NULL;
    }
    msgSendList->list = CreateDlist();
    if(!(msgSendList->list)) {
        LOG_E("create ipd list failed!");
        goto MSG_SEND_LIST_INIT_ERR;
    }

#ifdef L0_DEVICE
    msgSendList->listMutex = osMutexNew(NULL);
    if(!(msgSendList->listMutex)) {
        LOG_E("create ipd list mutex failed!");
        goto MSG_SEND_LIST_INIT_ERR;
    }
#elif defined(L2_DEVICE)
    pthread_mutex_init(&(msgSendList->listMutex), NULL);
#endif

    msgSendList->msgIdCnt = 1;
    return msgSendList;
MSG_SEND_LIST_INIT_ERR:
    if(msgSendList) {
        free(msgSendList);
        msgSendList = NULL;
    }
    return NULL;
}

static void LocalNetmsgSendListDeinit(MsgSendListHandle msgSendList)
{
    DestroyDlist(&(msgSendList->list));

#ifdef L0_DEVICE
    osMutexDelete(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_destroy(&(msgSendList->listMutex));
#endif
    
    return;
}

static int8_t LocalNetMsgSendListNodeAdd(const MsgSendListHandle    msgSendList,
                                               LocalNetMsgSendNode *pMsgSendNode)
{
    int8_t ret = -1;

    addLogs("Add new msg send Node data to list!");
    pMsgSendNode->msgId = msgSendList->msgIdCnt;
    pMsgSendNode->sendCnt = 5;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    if (!InsertHdlist(msgSendList->list, pMsgSendNode, sizeof(LocalNetMsgSendNode))) { // 插入头部
        addLogs("InsertHdlist success!");
        ret = 0;
    } else {
        LOG_E("InsertHdlist failed!");
    }
    msgSendList->msgIdCnt++;
    if(0 == msgSendList->msgIdCnt) {
        msgSendList->msgIdCnt = 1;
    }
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif

    return ret;
}

static int cmpStrFun(const void* data1, const void* data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    const char *str1 = (const char *)data1;
    const char *str2 = (const char *)data2;
    return strcmp(str1, str2);
}

static int MsgIdCmp(const void* data1, const void* data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);

    int ret = -1;
    const uint8_t msgId = *(const uint8_t*)data1;
    const LocalNetMsgSendNode *srcMsgSendNode = (const LocalNetMsgSendNode*)data2;

    if(!data1 || !data2) {
        LOG_E("data1 or data2 is NULL!");
        return ret;
    }
    if(msgId == srcMsgSendNode->msgId) {
        ret = 0;
    }
    return ret;
}

static int DestDevIdCheckDataCmp(const void* data1, const void* data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    int ret = -1;
    const DestDevIdCheckData *DestDevIdCheckData = (const char*)data1;
    const NetBroadcastPara_t *para2 = (const NetBroadcastPara_t *)data2;

    addLogs("= = SubscribeCmp!");
    addLogs(DestDevIdCheckData->subscribe);
    
    if(FindVdlist(para2->subscribe, DestDevIdCheckData->subscribe, cmpStrFun)) {
        addLogs("= = Find the subscribe on the list: ");
        addLogs(DestDevIdCheckData->subscribe);
		if((0 == strncmp(DestDevIdCheckData->group, para2->group, 32))
        || (0 == strncmp(para2->group, "all", strlen("all") + 1))) {
            ret = 0;
        }
    }
    return ret;
}

static int PublishCmp(const void* data1, const void* data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    int ret = -1;
    const char *pPublish = data1;
    const NetBroadcastPara_t *para2 = (const NetBroadcastPara_t *)data2;

    if(FindVdlist(para2->publish, pPublish, cmpStrFun)) {
        addLogs("= = Find the pPublish on the list: ");
        addLogs(pPublish);
        ret = 0;
    }
    return ret;
}

static int TimeofDayCmp(const void* data1, const void* data2)
{
    const LocalNetMsgSendNode *para1 = (const LocalNetMsgSendNode*)data1;
    const LocalNetMsgSendNode *para2 = (const LocalNetMsgSendNode*)data2;

    return (para2->time.tv_sec - para1->time.tv_sec);
}
static int8_t LocalNetMsgSendListNodeDelete(const MsgSendListHandle msgSendList, uint8_t msgId)
{
    int8_t ret = -1;
    DeviceIdHang *pDeviceIdHang;
    DeviceIdHang *pDeviceIdHangNxt;
    LocalNetMsgSendNode *pMsgSendNode;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);    
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    Node_t * node = FindVdlist(msgSendList->list, &msgId, MsgIdCmp);    // 按值查找
    if(!node) { // 不存在该MsgId的成员
        addLogs("can not find member with this MsgId from the list!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pMsgSendNode = (LocalNetMsgSendNode*)(node->data);
    if(!pMsgSendNode) {
        LOG_E("the node data is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pDeviceIdHang = pMsgSendNode->pDestDevId;
    if(!pDeviceIdHang) {
        LOG_E("the destination deviceId is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    while(pDeviceIdHang) {
        pDeviceIdHangNxt = pDeviceIdHang->next;
        free(pDeviceIdHang);
        pDeviceIdHang = pDeviceIdHangNxt;
    }
    free(pMsgSendNode->msg);
    pMsgSendNode->msg = NULL;
    DeleteVdlist(msgSendList->list, &msgId, MsgIdCmp);    // 按值删除
    ret = 0;

MSG_SEND_LIST_DELETE_NODE_END:
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif
    
    return ret;
}

static int SendListPublishCmp(const void* data1, const void* data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    const char *pPublish = data1;
    const LocalNetMsgSendNode *para2 = (const LocalNetMsgSendNode *)data2;

    return strcmp(pPublish, para2->publish);
}

static void LocalNetMsgSendListNodeDeleteByPublish(const MsgSendListHandle msgSendList, const char *publish)
{
    // Node_t *node = NULL;
    DeviceIdHang *pDeviceIdHang;
    DeviceIdHang *pDeviceIdHangNxt;
    LocalNetMsgSendNode *pMsgSendNode;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);    
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif

    Node_t *node = FindVdlist(msgSendList->list, publish, SendListPublishCmp);    // 按值查找
    if(!node) { // 不存在该publish的成员
        LOG_I("can not find member with this MsgId from the list!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pMsgSendNode = (LocalNetMsgSendNode*)(node->data);
    if(!pMsgSendNode) {
        LOG_E("the node data is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    pDeviceIdHang = pMsgSendNode->pDestDevId;
    if(!pDeviceIdHang) {
        LOG_E("the destination deviceId is null!");
        goto MSG_SEND_LIST_DELETE_NODE_END;
    }
    while(pDeviceIdHang) {
        pDeviceIdHangNxt = pDeviceIdHang->next;
        free(pDeviceIdHang);
        pDeviceIdHang = pDeviceIdHangNxt;
    }
    free(pMsgSendNode->msg);
    pMsgSendNode->msg = NULL;
    DeleteVdlist(msgSendList->list, publish, SendListPublishCmp);    // 按值删除
    LOG_I("delete %s type msg node!", publish);

MSG_SEND_LIST_DELETE_NODE_END:
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif
}

static int8_t LocalNetMsgSendListDeletebyResp(const MsgSendListHandle msgSendList,
                const LocalNetMsgRespData *pMsgRespData)
{
    int8_t ret = -1;
    DeviceIdHang *pDeviceIdHang;
    DeviceIdHang *pDeviceIdHangPre;
    LocalNetMsgSendNode msgSendNode;
    LocalNetMsgSendNode *pMsgSendNode;
    memset(&msgSendNode, 0, sizeof(LocalNetMsgSendNode));
    msgSendNode.msgId = pMsgRespData->msgId;
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif
    Node_t *node = FindVdlist(msgSendList->list, &(pMsgRespData->msgId), MsgIdCmp);    // 按值查找
    if(!node) { // 不存在该MsgId的成员
        goto MSG_SEND_LIST_DELETE_DEST_END;
    }
    pMsgSendNode = (LocalNetMsgSendNode*)(node->data);
    if((NULL == pMsgSendNode) || (NULL == pMsgSendNode->pDestDevId)) {
        goto MSG_SEND_LIST_DELETE_DEST_END;
    }
    if(!(pMsgSendNode->pDestDevId->next)) {    // 该待发送消息中，仅有一个目标设备Id
        if(strncmp(pMsgSendNode->pDestDevId->destDevId, pMsgRespData->deviceId, DEVICE_ID_LEN)) {
            goto MSG_SEND_LIST_DELETE_DEST_END;
        }
        free(pMsgSendNode->pDestDevId);
        pMsgSendNode->pDestDevId = NULL;
        free(pMsgSendNode->msg);
        pMsgSendNode->msg = NULL;
        DeleteVdlist(msgSendList->list, &(pMsgSendNode->msgId), MsgIdCmp);    // 按值删除
        ret = 0;
    } else {    // 该待发送消息中，有一个以上目标设备Id
        pDeviceIdHang = pMsgSendNode->pDestDevId;
        if(!strncmp(pDeviceIdHang->destDevId, pMsgRespData->deviceId, DEVICE_ID_LEN)) {    // 收到的是第一个目标设备Id的回复
            pMsgSendNode->pDestDevId = pDeviceIdHang->next;
            free(pDeviceIdHang);
            pDeviceIdHang = NULL;
            ret = 0;
            goto MSG_SEND_LIST_DELETE_DEST_END;
        }
        while(pDeviceIdHang) {
            pDeviceIdHangPre = pDeviceIdHang;
            pDeviceIdHang = pDeviceIdHang->next;
            if(!strncmp(pDeviceIdHang->destDevId ,pMsgRespData->deviceId, DEVICE_ID_LEN)) {
                pDeviceIdHangPre->next = pDeviceIdHang->next;
                free(pDeviceIdHang);
                pDeviceIdHang = NULL;
                ret = 0;
                goto MSG_SEND_LIST_DELETE_DEST_END;
            }
        }
        LOG_E("can not find destDeviceId from the member!");
    }
MSG_SEND_LIST_DELETE_DEST_END:
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif
    return ret;
}

static LocalNetMsgSendNode* LocalNetMsgSendListNodeGet(const MsgSendListHandle msgSendList)
{
    if(!msgSendList || !(msgSendList->list) || !(msgSendList->list->after)) {
        LOG_E("msgSendList is null or empty!");
        return NULL;
    }
#ifdef L0_DEVICE
    osMutexAcquire(msgSendList->listMutex, osWaitForever);    
#elif defined(L2_DEVICE)
    pthread_mutex_lock(&(msgSendList->listMutex));
#endif
    // 按照时间顺序排序
    SelectSortdlist(msgSendList->list,TimeofDayCmp);
#ifdef L0_DEVICE
    osMutexRelease(msgSendList->listMutex);
#elif defined(L2_DEVICE)
    pthread_mutex_unlock(&(msgSendList->listMutex));
#endif
    
    return (LocalNetMsgSendNode*)(msgSendList->list->after->data);
}

int8_t LocalNetMsgRecvCbReg(int8_t (*recvCb)(const char *msg))
{
    g_localNetCommCtl.recvCb = recvCb;
    return 0;
}

int8_t LocalNetDevListNoticeCbReg(int8_t (*devListNoticeCb)(Node_t *devList))
{
    g_localNetCommCtl.devListNoticeCb = devListNoticeCb;
    return 0;
}

static int8_t responseMsgPrase(const cJSON* respJson, ResponsePara_t *resp)
{
    cJSON *tempValue = NULL;

    if(respJson == NULL || resp == NULL) {
        LOG_E("NULL POINT! \n");
        return -1;
    }

    tempValue = cJSON_GetObjectItem(respJson, "id");
    if (!tempValue) {
        addLogs("resp msg id is null!");
        return -1;
    }
    addLogs("parse resp DevId");
    addLogs(cJSON_GetStringValue(tempValue));
    strcpy(resp->id, cJSON_GetStringValue(tempValue));

    tempValue = cJSON_GetObjectItem(respJson, "result");
    if (!tempValue) {
        addLogs("resp msg result is null!");
        return -1;
    }
    strcpy(resp->result, cJSON_GetStringValue(tempValue));

    tempValue = cJSON_GetObjectItem(respJson, "state");
    if (!tempValue) {
        addLogs("resp msg state is null!");
        return -1;
    }
    resp->state = (enum ResponseState)tempValue->valueint;

    return 0;
}

static int8_t groupCheck(char* group)
{
    if ((NULL == group)
    || (NULL == g_localNetCommCtl.onlineDevList)
    || (NULL == g_localNetCommCtl.onlineDevList->after)
    || (NULL == g_localNetCommCtl.onlineDevList->after->data)) {
        addLogs("selfDevInfo or boardcast group data is null!");
        return -1;
    }
    NetBroadcastPara_t *pSelfDevInfo = (NetBroadcastPara_t*)(g_localNetCommCtl.onlineDevList->after->data);

    // 两设备为同一个group
    if (0 == strncmp(pSelfDevInfo->group, group, strlen(pSelfDevInfo->group))) {
        return 0;
    }
    // 设备自身为L2
    if (0 == strncmp(pSelfDevInfo->group, "all", strlen("all"))) {
        return 0;
    }
    // 对方设备为L2
    if(0 == strncmp(group, "all", strlen("all"))) {
        return 0;
    }

    addLogs("dev is not at same group!");
    return -1;
}

static int8_t boardcastMsgParse(const char* msg, NetBroadcastPara_t *broadcast)
{
    if (!msg || !broadcast) {
        return -1;
    }
    cJSON *tempValue = NULL;
    cJSON *broadJson = cJSON_Parse(msg);
    if(!broadJson) {
        return -1;
    }
    cJSON *deviceJson = cJSON_GetObjectItem(broadJson, "device");
    if(!deviceJson) {
        goto BROADCAST_PARSE_ERR;
    }
    tempValue = cJSON_GetObjectItem(deviceJson, "id");
    if (tempValue) {
        strncpy(broadcast->id, cJSON_GetStringValue(tempValue), DEVICE_ID_LEN - 1);
    }
    tempValue = cJSON_GetObjectItem(deviceJson, "name");
    if (tempValue) {
        strncpy(broadcast->name, cJSON_GetStringValue(tempValue), strlen(cJSON_GetStringValue(tempValue)) + 1);
    }
    tempValue = cJSON_GetObjectItem(deviceJson, "type");
    if (tempValue) {
        strncpy(broadcast->type, cJSON_GetStringValue(tempValue), strlen(cJSON_GetStringValue(tempValue)) + 1);
    }
    tempValue = cJSON_GetObjectItem(deviceJson, "group");
    if (tempValue) {
        if(0 != groupCheck(cJSON_GetStringValue(tempValue))) {
            goto BROADCAST_PARSE_ERR;
        }
        strncpy(broadcast->group, cJSON_GetStringValue(tempValue), strlen(cJSON_GetStringValue(tempValue)) + 1);
    }
    tempValue = cJSON_GetObjectItem(deviceJson, "priority");
    if (tempValue) {
        broadcast->priority = tempValue->valueint;
    }
    // parse subscribe []
    broadcast->subscribe = CreateDlist();
    tempValue = cJSON_GetObjectItem(broadJson, "subscribe");
    if (!broadcast->subscribe || !tempValue) {
        goto BROADCAST_PARSE_ERR;
    }
    int tempArrSize = cJSON_GetArraySize(tempValue);
    if (tempArrSize > 0) {
        cJSON *jsonArrItem = NULL;
        for (int i = 0; i < tempArrSize; i++) {
            jsonArrItem = cJSON_GetArrayItem(tempValue, i);
            if (jsonArrItem) {
                InsertTdlist(broadcast->subscribe, cJSON_GetStringValue(jsonArrItem), strlen(cJSON_GetStringValue(jsonArrItem)) + 1);
            }
        }
    }
    // parse publish []
    broadcast->publish = CreateDlist();
    tempValue = cJSON_GetObjectItem(broadJson, "publish");
    if (!broadcast->publish || !tempValue) {
        goto BROADCAST_PARSE_ERR;
    }
    tempArrSize = cJSON_GetArraySize(tempValue);
    if (tempArrSize > 0) {
        cJSON *jsonArrItem = NULL;
        for (int i = 0; i < tempArrSize; i++) {
            jsonArrItem = cJSON_GetArrayItem(tempValue, i);
            if (jsonArrItem) {
                InsertTdlist(broadcast->publish, cJSON_GetStringValue(jsonArrItem), strlen(cJSON_GetStringValue(jsonArrItem)) + 1);
            }
        }
    }
    cJSON_Delete(broadJson);
    return 0;
BROADCAST_PARSE_ERR:
    cJSON_Delete(broadJson);
    return -1;
}

static int8_t unicastMsgParse(const cJSON *unicastJson, NetUnicastPara_t *unicast)
{
    if (unicastJson == NULL || unicast == NULL) {
        LOG_E("NULL POINT! \n");
        return -1;
    }
    cJSON *publishJson = cJSON_GetObjectItem(unicastJson, "publish");
    if(!publishJson) {
        LOG_E("publish is null!");
        return -1;
    }
    strcpy(unicast->publish, cJSON_GetStringValue(publishJson));
    cJSON *params = cJSON_GetObjectItem(unicastJson, "params");
    if (!params) {
        LOG_E("params is null!");
        return -1;
    }
    const char* paramsStr = cJSON_Print(params);
    memset(unicast->params, 0, sizeof(unicast->params));
    strcpy(unicast->params, paramsStr);
    free(paramsStr);
    paramsStr = NULL;

    return 0;
}

int cmpStrDeviceIdFun(const void* data1, const void* data2)
{
    SYSERR(NULL, ==, data1, "data1 == null", -1);
    SYSERR(NULL, ==, data2, "data2 == null", -1);
    const char *para1 = (const char *)data1;
    const NetBroadcastPara_t *para2 = (const NetBroadcastPara_t *)data2;
    return strcmp(para1, para2->id);
}

static int8_t dealBroadcastMsg(const char *broadcastData)
{
    NetBroadcastPara_t broadcastPara = {0};
    if(!broadcastData || boardcastMsgParse(broadcastData, &broadcastPara)) {
        LOG_E("boardcastMsgPrase error!");
        return -1;
    }
    // 更新广播消息时间戳
    gettimeofday(&(broadcastPara.time), NULL);
    if (g_localNetCommCtl.onlineDevList) {
        Node_t *foundNode = FindVdlist(g_localNetCommCtl.onlineDevList, broadcastPara.id, cmpStrDeviceIdFun);
        if (foundNode) {
            NetBroadcastPara_t *theFoundData = (NetBroadcastPara_t *)foundNode->data;
            if (theFoundData != NULL) {
                gettimeofday(&(theFoundData->time), NULL);
            } else {
                NetBroadcastPara_t *broadcast = malloc(sizeof(NetBroadcastPara_t));
                if (broadcast == NULL) {
                    return -1;
                }
                memcpy(broadcast, &broadcastPara, sizeof(NetBroadcastPara_t));
                foundNode->data = broadcast;
            }
        } else {
            NetBroadcastPara_t *broadcast = malloc(sizeof(NetBroadcastPara_t));
            if (broadcast == NULL) {
                return -1;
            }
            memcpy(broadcast, &broadcastPara, sizeof(NetBroadcastPara_t));
            InsertTdlist(g_localNetCommCtl.onlineDevList, broadcast, sizeof(NetBroadcastPara_t));
            if(g_localNetCommCtl.devListNoticeCb) {
                g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
            }
        }
    } else {
        NetBroadcastPara_t *broadcast = malloc(sizeof(NetBroadcastPara_t));
        if (broadcast == NULL) {
            return -1;
        }
        memcpy(broadcast, &broadcastPara, sizeof(NetBroadcastPara_t));
        g_localNetCommCtl.onlineDevList = CreateDlist();
        if (g_localNetCommCtl.onlineDevList) {
            InsertTdlist(g_localNetCommCtl.onlineDevList, broadcast, sizeof(NetBroadcastPara_t));
            if(g_localNetCommCtl.devListNoticeCb) {
                g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
            }
        }
    }
    return 0;
}

static int8_t LocalNetUnicastResponse(const char *pDestDeviceId, const char *pSelfDeviceId, const uint8_t tempId)
{
    int8_t ret = -1;
#if (PRINT_TIME)
//  for test time
    u32 time1 = getMillionSecond();
#endif
    cJSON *dataJson = cJSON_CreateObject();
    cJSON_AddStringToObject(dataJson, "messageType", RESPONSE);
    cJSON_AddNumberToObject(dataJson, "messageId", tempId);
    cJSON *msgJson = cJSON_CreateObject();
    cJSON_AddStringToObject(msgJson, "id", pSelfDeviceId);
    cJSON_AddStringToObject(msgJson, "result", "OK");
    cJSON_AddNumberToObject(msgJson, "state", 200);
    cJSON_AddItemToObject(dataJson, "message", msgJson);
    char *sendData = cJSON_Print(dataJson);
    cJSON_Delete(dataJson);
    addLogs("sendData:");
    addLogs(sendData);
    addLogs("destDeviceID:");
    addLogs(pDestDeviceId);

    if (sendData != NULL) {
        LocalNetUdpSend(sendData, pDestDeviceId);
        ret = 0;
        free(sendData);
        sendData = NULL;
    }
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    return ret;
}

void PRINT_SUBSCRIBE_LIST(Node_t *head)
{
    addLogs("PRINT_SUBSCRIBE_LIST");
    if (head == NULL) {
        LOG_E("LIST IS NULL! \n");
        return;
    }
    Node_t *temp = head->after;
    while(temp != head && NULL != temp->data) {
        addLogs(temp->data);
        temp = temp->after;
    }
}

static int8_t dealUniCastMsg(const cJSON *jsonTempData, const char *pDeviceId, const uint8_t tempId)
{
#if (PRINT_TIME)
    u32 time1 = getMillionSecond();
#endif
    NetUnicastPara_t singlePublishPara = {0};
    NetBroadcastPara_t *theFoundNetData = NULL;
    if (unicastMsgParse(jsonTempData, &singlePublishPara) < 0) {
        LOG_E("unicastMsgPrase error! \n");
        return -1;
    }
    if (g_localNetCommCtl.onlineDevList == NULL) {
        LOG_E("ERROR! no onlineDevList! \n");
        return -1;
    }

    Node_t *foundNode = FindVdlist(g_localNetCommCtl.onlineDevList, pDeviceId, cmpStrDeviceIdFun);
    if (foundNode) {
        theFoundNetData = (NetBroadcastPara_t *)(foundNode->data);
        // 更新发单播设备时间戳
        gettimeofday(&(theFoundNetData->time), NULL);
    }
    if (g_localNetCommCtl.onlineDevList->after != NULL &&
        g_localNetCommCtl.onlineDevList->after->data != NULL &&
		g_localNetCommCtl.recvCb != NULL) {
        NetBroadcastPara_t *tempNetBroPara = (NetBroadcastPara_t *)(g_localNetCommCtl.onlineDevList->after->data);
        Node_t *foundSubscribeNode = FindVdlist(tempNetBroPara->subscribe, singlePublishPara.publish, cmpStrFun);
        if (foundSubscribeNode) {
            // 使用该回调
            char *msgString = cJSON_Print(jsonTempData);
            // 增加group
            if(theFoundNetData) {
                cJSON *msgJson = cJSON_Parse(msgString);
                free(msgString);
                msgString = NULL;
                // 增加group
                cJSON_AddStringToObject(msgJson, "group", theFoundNetData->group);
                msgString = cJSON_Print(msgJson);
                cJSON_Delete(msgJson);
                addLogs(" foundSubscribeNode msgString：");
                addLogs(msgString);
            }
            g_localNetCommCtl.recvCb(msgString);
            free(msgString);
            msgString = NULL;
        } else {
            addLogs("singlePublishPara.publish");
            addLogs(singlePublishPara.publish);
        }
        LocalNetUnicastResponse(pDeviceId, tempNetBroPara->id,tempId);
    }
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    return 0;
}

static int8_t dealResponseMsg(const cJSON *jsonTempData, const uint8_t tempId)
{
    ResponsePara_t responsePara;
    if (responseMsgPrase(jsonTempData, &responsePara) < 0) {
        LOG_E("responseParaPrase error!");
        return -1;
    }
    Node_t *tempNetBroPara = g_localNetCommCtl.onlineDevList;
    NetBroadcastPara_t *foundResonseNode = (NetBroadcastPara_t *)FindVdlist(tempNetBroPara, 
                                                                    responsePara.id, cmpStrDeviceIdFun);
    if (foundResonseNode) {
        gettimeofday(&(foundResonseNode->time) ,NULL);
    }

    // 根据msg id删除对应的事件 tempId
    LocalNetMsgRespData localNetMsgRespData;
    localNetMsgRespData.msgId = tempId;
    strncpy(localNetMsgRespData.deviceId, responsePara.id, DEVICE_ID_LEN - 1);
    // Printdlist(g_localNetCommCtl.sendReadyMsgList->list, SendMsgListNodePrintFun);
    LocalNetMsgSendListDeletebyResp(g_localNetCommCtl.sendReadyMsgList, &localNetMsgRespData);

    return 0;
}

#ifdef L0_DEVICE
void LocalNetCommunicationCtl(void *arg)
#elif defined(L2_DEVICE)
void *LocalNetCommunicationCtl(void *arg)
#endif
{
#ifdef L0_DEVICE
    UNUSED(arg);
#endif
    cJSON *jsonRoot = NULL;
    cJSON *jsonTempType = NULL;
    cJSON *jsonTempId = NULL;
    cJSON *jsonTempData = NULL;
    LocalNetMsgRecv *pMsgRecv = NULL;
    g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_RUNNING;

    while(LOCAL_NET_THREAD_RUNNING == g_localNetCommCtl.recvMsgDealThreadStatus) {
#if (PRINT_TIME)
        // for test time
        u32 time1 = getMillionSecond();
#endif
        // recv queue
#ifdef L0_DEVICE
        int32_t res = osMessageQueueGet(g_localNetCommCtl.recvMsgDealQueue, &pMsgRecv,0, 0);
        if(osOK != res) {
            addLogs("mqueue recv data failed!");
            osDelay(Time2Tick(300));
            continue;
        }
#elif defined(L2_DEVICE)
        addLogs("LocalNetCommunicationCtl g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_RUNNING;");
        pMsgRecv = (LocalNetMsgRecv *)malloc(sizeof(LocalNetMsgRecv));
        if (!pMsgRecv) {
            usleep(300000);
            continue;
        }
        addLogs("LocalNetCommunicationCtl pMsgRecv create succ");

        if (local_queue_get_comm(g_localNetCommCtl.recvMsgDealQueue, pMsgRecv, sizeof(LocalNetMsgRecv)) < 0) {
            addLogs("LocalNetCommunicationCtl mqueue recv data failed!");
            free(pMsgRecv);
            pMsgRecv = NULL;
            {
                char errmsg[128] = {0};
                sprintf(errmsg, "%d[%s]", errno, strerror(errno));
                addLogs((const char *)errmsg);
            }
            usleep(300000);
            continue;
        } else {
            addLogs("local_queue_get_comm msg get succ: ");
        }

#if (PRINT_TIME)
        // for test time
    {
        char tmp[32] = {0};
        sprintf("recv cost time : %d(ms)", (int)(getMillionSecond() - time1));
        addLogs(tmp);
        time1 = getMillionSecond();
    }
#endif
#endif
        // parse msg
        addLogs("LocalNetCommunicationCtl receive data pMsgRecv->data: ");
        addLogs(pMsgRecv->data);
        
        jsonRoot = cJSON_Parse((char *)(pMsgRecv->data));
        if( jsonRoot == NULL) {
            LOG_E("msg json parse failed!");
            free(pMsgRecv);
            pMsgRecv = NULL;
            addLogs("msg json parse failed!");
            continue;
        } 

        jsonTempType = cJSON_GetObjectItem(jsonRoot, "messageType"); // msg type
        
        if (jsonTempType == NULL) {
            addLogs("cJSON_GetObjectItem messageType failed! \n");
            cJSON_Delete(jsonRoot);
            free(pMsgRecv);
            pMsgRecv = NULL;
            continue;
        }

        jsonTempId = cJSON_GetObjectItem(jsonRoot, "messageId"); // msg Id
        if (jsonTempId == NULL) {
            addLogs("This meaasge have no messageId, Maybe a broadcast!");
        }
        jsonTempData = cJSON_GetObjectItem(jsonRoot, "message"); // msg
        if (jsonTempData == NULL) {
            cJSON_Delete(jsonRoot);
            free(pMsgRecv);
            pMsgRecv = NULL;
            LOG_E("cJSON_GetObjectItem message failed! \n");
            continue;
        }
        const char *pMsgeData = cJSON_Print(jsonTempData);
        if (!strcmp(cJSON_GetStringValue(jsonTempType), BROADCAST)) { // 广播
            addLogs("received broadcast");
            dealBroadcastMsg(pMsgeData);
        }
        else if (!strcmp(cJSON_GetStringValue(jsonTempType), UNICAST)) { // 单播
            addLogs("received unicast");
            addLogs(cJSON_Print(jsonTempData));
            dealUniCastMsg(jsonTempData, pMsgRecv->deviceId, jsonTempId->valueint);
        }
        else if (!strcmp(cJSON_GetStringValue(jsonTempType), RESPONSE)) { // 回复
            addLogs("deal response msg");
            dealResponseMsg(jsonTempData, jsonTempId->valueint);
            addLogs("after deal response msg");
        }
        cJSON_Delete(jsonRoot);
        free(pMsgeData);
        pMsgeData = NULL;
        free(pMsgRecv);
        pMsgRecv = NULL;

        // for test time
        #if (PRINT_TIME)
        {
            char tmp[32] = {0};
            sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
            addLogs(tmp);
        }
        #endif
    }

    if(LOCAL_NET_THREAD_RELEASE == g_localNetCommCtl.recvMsgDealThreadStatus) {
        g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_EXIT;
    }
    else {
        g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_ERR;
        LOG_E("recvMsgDealThread release error!");
    }

#ifdef L0_DEVICE
    return;
#elif defined(L2_DEVICE)
    return NULL;    
#endif
}

#ifdef L0_DEVICE
void LocalNetMsgSendDeal(void *arg)
#elif defined(L2_DEVICE)
void *LocalNetMsgSendDeal(void *arg)
#endif
{
#ifdef L0_DEVICE
    UNUSED(arg);
#endif
    char *sendMsg = NULL;
    struct timeval curTimeval;
    DeviceIdHang *pDeviceIdHang = NULL;
    LocalNetMsgSendNode *pMsgSendNode = NULL;
    memset(&curTimeval, 0, sizeof(struct timeval));
    while(1) {
    #if (PRINT_TIME)
        // for test time
        u32 time1 = getMillionSecond();
    #endif
        gettimeofday(&curTimeval, NULL);
        pMsgSendNode = LocalNetMsgSendListNodeGet(g_localNetCommCtl.sendReadyMsgList);
        if(pMsgSendNode == NULL || ((5 > pMsgSendNode->sendCnt) && (5 > (curTimeval.tv_sec - pMsgSendNode->time.tv_sec)))) {
#ifdef L0_DEVICE
            // LOG_I("no msg need to send.");
            osDelay(Time2Tick(300));
#elif defined(L2_DEVICE)
            usleep(300000);
#endif
            continue;
        }

        addLogs("LocalNetMsgSendDeal send msg : "); 
        addLogs(pMsgSendNode->msg);

        // 制作发送数据
        cJSON *msg = cJSON_CreateObject();
        cJSON_AddStringToObject(msg, "messageType", UNICAST);
        cJSON_AddNumberToObject(msg, "messageId", pMsgSendNode->msgId);
        cJSON *msgBody = cJSON_Parse(pMsgSendNode->msg);
        cJSON_AddItemToObject(msg, "message", msgBody);
        sendMsg = cJSON_Print(msg);
        pDeviceIdHang = pMsgSendNode->pDestDevId;

        while(pDeviceIdHang) {
        #if (PRINT_TIME)
            u32 time2 = getMillionSecond();
        #endif
            addLogs("sendMsg, pDeviceIdHang->destDevId: ");
            addLogs(sendMsg);
            addLogs(pDeviceIdHang->destDevId);

            LocalNetUdpSend(sendMsg, pDeviceIdHang->destDevId);
            pDeviceIdHang = pDeviceIdHang->next;

            // for test time
            #if (PRINT_TIME)
            {
                char tmp[32] = {0};
                sprintf("%s pDeviceIdHang loop cost time : %d(ms)", __func__, (int)(getMillionSecond() - time2));
                addLogs(tmp);
            }
            #endif
        }
        pMsgSendNode->time.tv_sec = curTimeval.tv_sec;
        pMsgSendNode->sendCnt--;
        if(!(pMsgSendNode->sendCnt)) { // 重发已到最大次数
            LocalNetMsgSendListNodeDelete(g_localNetCommCtl.sendReadyMsgList, pMsgSendNode->msgId);
        }
        free(sendMsg);
        sendMsg = NULL;
        cJSON_Delete(msg);
        #if (PRINT_TIME)
        // for test time
        {
            char tmp[32] = {0};
            sprintf("%s  one loop cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
            addLogs(tmp);
        }
        #endif
    }
}

/**
* @brief 广播发送的设备信息+订阅、发布信息
*
{
    "device":{
        "name":"RK3568 parking background management system"
        "type" : "parkingSystem", 
        "id" : "97234126", 
        "priority": 250，
        "group" : "all",
    }，
    "subscribe" : [
    "carApproachDetect"，"licensePlateRecognition","latchChange"
    ],
    "publish" : ["latchControl"]
}
*/
static int8_t LocalNetDevInfoMake(char *broadcastBuf, void *data)
{
    if (!broadcastBuf || !data) {
        return -1;
    }
    NetBroadcastPara_t *tempNetBroPara = (NetBroadcastPara_t *)data;
    char *pBroadCastMsg = NULL;
    cJSON *broadCastJson = cJSON_CreateObject();
    cJSON_AddStringToObject (broadCastJson, "messageType", BROADCAST);
    cJSON *messageJson = cJSON_CreateObject();
    cJSON *deviceJson = cJSON_AddObjectToObject(messageJson, "device");
    cJSON_AddStringToObject(deviceJson, "name", tempNetBroPara->name);
    cJSON_AddStringToObject(deviceJson, "type", tempNetBroPara->type);
    char mac[32] = {};
#ifdef L0_DEVICE
    const char *netDeviceName = "wlan0";    
#elif defined(L2_DEVICE)
    const char *netDeviceName = WLAN_NAME;   
#endif
    int getmacret = getLocalMacAddr(netDeviceName, mac, 32);
    if(getmacret >= 0) {
        char idArr[512] = {};
        sprintf(idArr, "%s_%s_%s", tempNetBroPara->type, tempNetBroPara->group, mac);
        char sha256ID[256] = {};
        StrSha256(idArr, strlen(idArr), sha256ID);
        cJSON_AddStringToObject(deviceJson, "id", sha256ID);
        bzero(tempNetBroPara->id, sizeof(tempNetBroPara->id));
        sprintf(tempNetBroPara->id, "%s", sha256ID);
        cJSON_AddNumberToObject(deviceJson, "priority", tempNetBroPara->priority);
        cJSON_AddStringToObject(deviceJson, "group", tempNetBroPara->group);
        // subscribe
        cJSON *subscribe = cJSON_AddArrayToObject(messageJson, "subscribe");
        if (tempNetBroPara->subscribe && tempNetBroPara->subscribe->after) {
            Node_t *tmp_subscribe = tempNetBroPara->subscribe->after;
            while (tmp_subscribe != tempNetBroPara->subscribe) {
                char *tmpSubContent = tmp_subscribe->data;
                cJSON *tmpSubJsonItem = cJSON_CreateString(tmpSubContent);
                cJSON_AddItemToArray(subscribe, tmpSubJsonItem);
                tmp_subscribe = tmp_subscribe->after;
            }
        }
        // publish
        cJSON *publish = cJSON_AddArrayToObject(messageJson, "publish");
        if (tempNetBroPara->publish && tempNetBroPara->publish->after) {
            Node_t *tmp_publish= tempNetBroPara->publish->after;
            while (tmp_publish != tempNetBroPara->publish) {
                char *tmpPubContent = tmp_publish->data;
                cJSON *tmpPubJsonItem = cJSON_CreateString(tmpPubContent);
                cJSON_AddItemToArray(publish, tmpPubJsonItem);
                tmp_publish = tmp_publish->after;
            }
        }
        cJSON_AddItemToObject(broadCastJson, "message", messageJson);
        pBroadCastMsg = cJSON_Print(broadCastJson);
        // sendBroadCastBuf
        bzero(broadcastBuf, BROADCAST_ARRSIZE);
        snprintf(broadcastBuf, strlen(pBroadCastMsg) + 1, "%s", pBroadCastMsg);
        cJSON_Delete(broadCastJson);
		free(pBroadCastMsg);
        pBroadCastMsg = NULL;
    }

    return 0;
}

int8_t LocalNetDevAttributeBoardCast(void)
{
    int8_t ret = -1;
    time_t t;
    /* 初始化随机数发生器 */
    srand((unsigned) time(&t));
    // 开线程、发广播
    if (g_localNetCommCtl.onlineDevList && g_localNetCommCtl.onlineDevList->after->data) {
        char broadcastBuf[BROADCAST_ARRSIZE] = {0};
        // 创建广播报文
        LocalNetDevInfoMake(broadcastBuf, g_localNetCommCtl.onlineDevList->after->data);
        // 开启线程
        uint8_t interval = 8 + rand() % 8;
#if PRINT
        char span[256] = {0};
        sprintf(span, "LocalNetUdpBoardcast interval : %d", interval);
        addLogs(span);
#endif
        if(LocalNetUdpBoardcast(broadcastBuf, interval) == 0) {
            ret = 0;
        }
    }
    return ret;
}

#ifdef L0_DEVICE
static void LocalNetDevOfflineJudge(void *arg)
#elif defined(L2_DEVICE)
static void* LocalNetDevOfflineJudge(void *arg)
#endif
{
    struct timeval curTimeval;
    g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_RUNNING;
    while(LOCAL_NET_THREAD_RUNNING == g_localNetCommCtl.devOfflineJudgeThreadStatus) {
        if (g_localNetCommCtl.onlineDevList) {
            // 循环 netOnlineDeviceDList 查找订阅
            Node_t *tmpNetOnlineDeviceDList = g_localNetCommCtl.onlineDevList->after;
            NetBroadcastPara_t *tempNetBroPara = (NetBroadcastPara_t *)tmpNetOnlineDeviceDList->data;
            while (tempNetBroPara && tmpNetOnlineDeviceDList != g_localNetCommCtl.onlineDevList) {
                gettimeofday(&curTimeval, NULL);
                DeviceNetState hisState = tempNetBroPara->state;
                if (curTimeval.tv_sec - tempNetBroPara->time.tv_sec >= 40) {
#if PRINT
                    char span[256] = {0};
                    sprintf(span, " curTimeval.tv_sec - tempNetBroPara->time.tv_sec >= 40: %ld",
                        curTimeval.tv_sec - tempNetBroPara->time.tv_sec);
                    addLogs(span);
#endif
                    tempNetBroPara->state = LOCAL_NET_OFFLINE;
                    if((g_localNetCommCtl.devListNoticeCb) && hisState == LOCAL_NET_ONLINE) {
                        g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
                    }
                } else {
#if PRINT
                    char span[256] = {0};
                    sprintf(span, " curTimeval.tv_sec - tempNetBroPara->time.tv_sec < 40: %ld",
                        curTimeval.tv_sec - tempNetBroPara->time.tv_sec);
                    addLogs(span);
#endif
                    tempNetBroPara->state = LOCAL_NET_ONLINE;
                    if((g_localNetCommCtl.devListNoticeCb) && hisState == LOCAL_NET_OFFLINE) {
                        g_localNetCommCtl.devListNoticeCb(g_localNetCommCtl.onlineDevList);
                    }
                }
                tmpNetOnlineDeviceDList = tmpNetOnlineDeviceDList->after;
                tempNetBroPara = (NetBroadcastPara_t *)tmpNetOnlineDeviceDList->data;
            }
        }
        sleep(3);
    }
    if(LOCAL_NET_THREAD_RELEASE == g_localNetCommCtl.devOfflineJudgeThreadStatus) {
        g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_EXIT;
    }
    else {
        g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_ERR;
        LOG_E("devOfflineJudgeThread release error!");
    }

#ifdef L0_DEVICE
    return;    
#elif defined(L2_DEVICE)
    return NULL;    
#endif
}

static uint8_t LocalNetGetNetStatus(void)
{
    int8_t ret = -1;

#ifdef L0_DEVICE
    if(0 < BOARD_GetWifiSignalLevel()) {
        ret = 0;
    }
#elif defined(L2_DEVICE)
    char mac[32] = {};
    const char *netDeviceName = WLAN_NAME; 
    int getmacret = getLocalMacAddr(netDeviceName, mac, 32);
    if(getmacret >= 0) {
        ret = 0;
    }
#endif

    return ret;
}

static DeviceIdHang* LocalNetOnlineDevSubscribeGet(DestDevIdCheckData *pDestDevIdCheckData)
{
    Node_t *firstNode = NULL;
    DeviceIdHang *pDevIdHangNext = NULL;
    DeviceIdHang *pDevIdHangNode = NULL;
    NetBroadcastPara_t *pOnlineDevInfo = NULL;

    Node_t *node = g_localNetCommCtl.onlineDevList->after;
    if(!node) {
        LOG_E("onlineDevList is NULL!");
        return NULL;
    }

    firstNode = FindVdlist(node, pDestDevIdCheckData, DestDevIdCheckDataCmp);
    if(!firstNode) {
        addLogs("no member subscribe this publish on the list!");
        return NULL;
    }
    node = firstNode;
    // 为找到的devId申请内存
    pDevIdHangNode = malloc(sizeof(DeviceIdHang));
    if(!pDevIdHangNode) {
        LOG_E("malloc pDevIdHangNode failed!");
        return NULL;
    }
    memset(pDevIdHangNode, 0, sizeof(DeviceIdHang));
    // 将找到的节点按照设备信息的格式整理
    pDevIdHangNode->next = NULL;
    pOnlineDevInfo = (NetBroadcastPara_t*)(node->data);
    strcpy(pDevIdHangNode->destDevId, pOnlineDevInfo->id);
    while(1) {
        pDevIdHangNext = pDevIdHangNode;
        node = FindVdlist(node, pDestDevIdCheckData, DestDevIdCheckDataCmp);
        if((!node) || (firstNode == node)) { // 不存在订阅该publish的成员
            addLogs("have search all member of the list!");
            break;
        }
        // 为找到的devId申请内存
        pDevIdHangNode = malloc(sizeof(DeviceIdHang));
        if(!pDevIdHangNode) {
            LOG_E("malloc pDevIdHangNode failed!");
            while(pDevIdHangNode){
                pDevIdHangNext = pDevIdHangNode->next;
                free(pDevIdHangNode);
                pDevIdHangNode = pDevIdHangNext;
            }
            return NULL;
        }
        memset(pDevIdHangNode, 0, sizeof(DeviceIdHang));
        pDevIdHangNode->next = pDevIdHangNext;
        // 将找到的节点按照设备信息的格式整理
        pOnlineDevInfo = (NetBroadcastPara_t*)node->data;
        strcpy(pDevIdHangNode->destDevId, pOnlineDevInfo->id);
    }

    return pDevIdHangNode;
}

static int8_t publishCheck(const char *publish)
{
    int8_t ret = -1;
    if (publish == NULL) {
        return ret;
    }
    Node_t *firstNode = NULL;
    NetBroadcastPara_t *selfDevInfo = (NetBroadcastPara_t *)g_localNetCommCtl.onlineDevList->after->data;

    Node_t *node = g_localNetCommCtl.onlineDevList->after;
    if(node == NULL) {
        addLogs("onlineDevList is NULL!");
        LOG_E("onlineDevList is NULL!");
        return ret;
    }
    firstNode = FindVdlist(node, publish, PublishCmp);
    if(!firstNode) {
        addLogs("no member have this publish on the list!");
        LOG_E("no member have this publish on the list!");
        ret = 0;
        return ret;
    }
    node = firstNode;
    while(1) {
        NetBroadcastPara_t *samePublishDevInfo = node->data;
        if(samePublishDevInfo && (samePublishDevInfo->priority > selfDevInfo->priority)) {
            addLogs("have online device priority higher than self device.");
            break;
        }
        node = FindVdlist(node, publish, PublishCmp);
        if((!node) || (firstNode == node)) {
            addLogs("have search all member of the list!");
            ret = 0;
            break;
        }
    }
    return ret;
}

int8_t LocalNetMsgSend(const char *publish, const char *params)
{
    int8_t ret = -1;
    if (publish == NULL || params == NULL) {
        return ret;
    }

    char *sendMsg = NULL;
    cJSON *msg = NULL;
    LocalNetMsgSendNode msgSendNode;
    DestDevIdCheckData destDevIdCheckData;
    // 判断当前publish是否有更高级的设备
    if(publishCheck(publish)) {
        addLogs("can not publish this commond!");
        return ret;
    }
    addLogs("could publish this commond!");
 #if (PRINT_TIME)
    // test for time
    u32 time1 = getMillionSecond();
#endif
    // 制作发送数据
    msg = cJSON_CreateObject();
    if (msg == NULL) {
        return ret;
    }
    cJSON_AddStringToObject(msg, "publish", publish);
    cJSON *paramsJson = cJSON_Parse(params);
    if (paramsJson == NULL) {
        return ret;
    }
    memset(&destDevIdCheckData, 0, sizeof(destDevIdCheckData));
    cJSON *groupJson = cJSON_GetObjectItem(paramsJson, "group"); // msg type valuestring
    if (groupJson != NULL) {
        addLogs("msg have group, is L2 device!");
        strncpy(destDevIdCheckData.group, cJSON_GetStringValue(groupJson), sizeof(destDevIdCheckData.group) - 1);
    } else {
        NetBroadcastPara_t *pNetBoardcastData = g_localNetCommCtl.onlineDevList->after->data;
        if(pNetBoardcastData) {
            addLogs("copy self group! to send msg");
            strncpy(destDevIdCheckData.group, pNetBoardcastData->group, sizeof(destDevIdCheckData.group) - 1);
        }
    }
    strncpy(destDevIdCheckData.subscribe, publish, sizeof(destDevIdCheckData.subscribe) - 1);
    cJSON_AddItemToObject(msg, "params", paramsJson);
    sendMsg = cJSON_Print(msg);
    if(!sendMsg) {
        return ret;
    }
    addLogs(" LocalNetMsgSend sendMsg: \n");
    addLogs(sendMsg);

    // 初始化发送信息节点
    memset(&msgSendNode, 0, sizeof(LocalNetMsgSendNode));
    // 获取发送目标
    msgSendNode.pDestDevId = LocalNetOnlineDevSubscribeGet(&destDevIdCheckData);
    if(!msgSendNode.pDestDevId) {
        free(sendMsg);
        sendMsg = NULL;
        cJSON_Delete(msg);
        return ret;
    }
    msgSendNode.msg = sendMsg;

    // 注释 重复命令发送功能
    strncpy(msgSendNode.publish, publish, strlen(publish) + 1);
    LocalNetMsgSendListNodeDeleteByPublish(g_localNetCommCtl.sendReadyMsgList, publish);
    
    if(-1 == LocalNetMsgSendListNodeAdd(g_localNetCommCtl.sendReadyMsgList, &msgSendNode)) {
        free(sendMsg);
        sendMsg = NULL;
        cJSON_Delete(msg);
        return ret;
    }
    #if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
    #endif
	
    cJSON_Delete(msg);
    ret = 0;
    return ret;
}

int8_t LocalNetSelfInfoSet(NetBroadcastPara_t *selfInfo)
{
    int8_t ret = -1;
    g_localNetCommCtl.onlineDevList = CreateDlist();
    if (g_localNetCommCtl.onlineDevList) {
        InsertHdlist(g_localNetCommCtl.onlineDevList, selfInfo, sizeof(NetBroadcastPara_t));
        ret = 0;
    }
    return ret;
}

static int8_t UdpRecvCb(const char *pMsg, const char *pDeviceId)
{
    int8_t ret = -1;
    if (pMsg == NULL) {
        return ret;
    }
    if (pDeviceId == NULL) {
        return ret;
    }

    uint16_t msgLen = 0;
    msgLen = strlen(pMsg);
    addLogs("UdpRecvCb msgLen: ");
    addLogs(pMsg);
#if (PRINT_TIME)
    // test for time
    u32 time1 = getMillionSecond();
#endif
    // no prt pRecvMsg
    LocalNetMsgRecv pRecvMsg = {0};
    memset(&pRecvMsg, 0, sizeof(LocalNetMsgRecv));
    pRecvMsg.dataLen = msgLen + 1;
    strncpy(pRecvMsg.deviceId, pDeviceId, DEVICE_ID_LEN  - 1);
    strncpy(pRecvMsg.data, pMsg, msgLen + 1);

    addLogs("UdpRecvCb pRecvMsg created data: ");
    addLogs(pRecvMsg.data);

    // udpSendData send queue
#ifdef L0_DEVICE
    if(osOK != osMessageQueuePut(g_localNetCommCtl.recvMsgDealQueue, &&pRecvMsg, 0, 0)) {
        LOG_E("osMessageQueuePut error.");
        goto UDP_RECV_CB_ERR;
    }
#elif defined(L2_DEVICE)

    if (local_queue_put_udp(g_localNetCommCtl.recvMsgDealQueue, &pRecvMsg, sizeof(LocalNetMsgRecv)) < 0) {
        addLogs("LocalNetCommunicationCtl mqueue send data failed!");
	    LOG_E("osMessageQueuePut error.");
        {
                char errmsg[128] = {0};
                sprintf(errmsg, "msg send err : %d[%s]", errno, strerror(errno));
                addLogs((const char *)errmsg);
        }
        goto UDP_RECV_CB_ERR;
    } else {
        addLogs("local_queue_put_udp msg send succ: ");
    }

#endif
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s success cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    ret = 0;
    return ret;

UDP_RECV_CB_ERR:
#if (PRINT_TIME)
    // for test time
    {
        char tmp[32] = {0};
        sprintf("%s failed cost time : %d(ms)", __func__, (int)(getMillionSecond() - time1));
        addLogs(tmp);
    }
#endif
    return ret;
}

int8_t LocalNetInit(void)
{
    int8_t ret = -1;
    addLogs("LocalNetInit!");

    if(LocalNetGetNetStatus()) {
        LOG_E("net is not connected!");
    }
    LocalNetUdpRecvCbReg(UdpRecvCb);
    addLogs("LocalNetUdpRecvCbReg!");

    if(LocalNetUdpInit()) {
        LOG_E("UDP init failed!");
    }
    addLogs("LocalNetUdpInit!");

    if(LocalNetDevAttributeBoardCast()) {
        LOG_E("boardcast start failed!");
    }
    addLogs("LocalNetDevAttributeBoardCast!");

#ifdef L0_DEVICE
    // create udp send msg queue.
    g_localNetCommCtl.recvMsgDealQueue = 
        osMessageQueueNew(MQ_MSG_NUM_MAX, MQ_MSG_SIZE_MAX, (osMessageQueueAttr_t*)NULL);
    if(NULL == g_localNetCommCtl.recvMsgDealQueue) {
        LOG_E("osMessageQueueNew faild!");
        return ret;
    }
#elif defined(L2_DEVICE)
    g_localNetCommCtl.recvMsgDealQueue = local_queue_init();
    if (g_localNetCommCtl.recvMsgDealQueue == 0) {
        addLogs("comm init queue failed");
        return ret;
    }

#endif

addLogs("LocalNetMsgSendListInit!");
    g_localNetCommCtl.sendReadyMsgList = LocalNetMsgSendListInit();
    if(NULL == g_localNetCommCtl.sendReadyMsgList) {
        LOG_E("msgSendList init faild!");
    }
    g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_INIT;
    g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_INIT;
    g_localNetCommCtl.sendMsgDealThreadStatus = LOCAL_NET_THREAD_INIT;
#ifdef L0_DEVICE
    osThreadAttr_t attr;
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.name = "OfflineJudge";
    attr.stack_size = 1024*4;
    attr.priority = 24;

    if ((g_localNetCommCtl.devOfflineJudgeThread = 
             osThreadNew((osThreadFunc_t)LocalNetDevOfflineJudge, NULL, &attr)) == NULL) {
        LOG_E("Could not create the recvMsgDeal thread.");
        return ret;
    }

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.name = "CommCtl";
    attr.stack_size = 1024*4;
    attr.priority = 24;
    if ((g_localNetCommCtl.recvMsgDealThread = 
             osThreadNew((osThreadFunc_t)LocalNetCommunicationCtl, NULL, &attr)) == NULL) {
        LOG_E("Could not create the recvMsgDeal thread.");
        return ret;
    }
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.name = "MsgSendDeal";
    attr.stack_size = 1024*4;
    attr.priority = 24;
    if ((g_localNetCommCtl.sendMsgDealThread = 
             osThreadNew((osThreadFunc_t)LocalNetMsgSendDeal, NULL, &attr)) == NULL) {
        LOG_E("Could not create the MsgSendDeal thread.");
        return ret;
    }
#elif defined(L2_DEVICE)
    // 开线程，检查设备是否掉线
    if(pthread_create(&(g_localNetCommCtl.devOfflineJudgeThread), NULL, LocalNetDevOfflineJudge, NULL) != EXEC_SUCC) {
        LOG_E("Could not create the LocalNetDevOfflineJudge thread.");
    }
    pthread_detach(g_localNetCommCtl.devOfflineJudgeThread);

    // 开线程，接收其他设备发送的信息
    if(pthread_create(&(g_localNetCommCtl.recvMsgDealThread), NULL, LocalNetCommunicationCtl, NULL) != EXEC_SUCC) {
        LOG_E("Could not create the LocalNetCommunicationCtl thread.");
    }
    pthread_detach(g_localNetCommCtl.recvMsgDealThread);
	
	// 开线程，信息发送的处理
    if(pthread_create(&(g_localNetCommCtl.sendMsgDealThread), NULL, LocalNetMsgSendDeal, NULL) != EXEC_SUCC) {
        LOG_E("Could not create the LocalNetMsgSendDeal thread.");
    }
    pthread_detach(g_localNetCommCtl.sendMsgDealThread);
#endif

    ret = 0;
    return ret;
}

int8_t LocalNetDeinit(void)
{
    local_queue_deinit(g_localNetCommCtl.recvMsgDealQueue);
    g_localNetCommCtl.sendMsgDealThreadStatus = LOCAL_NET_THREAD_RELEASE;
    g_localNetCommCtl.recvMsgDealThreadStatus = LOCAL_NET_THREAD_RELEASE;
    g_localNetCommCtl.devOfflineJudgeThreadStatus = LOCAL_NET_THREAD_RELEASE;

    LocalNetmsgSendListDeinit(g_localNetCommCtl.sendReadyMsgList);
    return 0;
}

Node_t *getOnlineDevList(void)
{
    return g_localNetCommCtl.onlineDevList;
}

